From 8a73a967e18c55199785bae0f22dc94d9b2f8985 Mon Sep 17 00:00:00 2001
From: Waldemar Brodkorb <wbrodkorb@conet.de>
Date: Tue, 27 Nov 2018 15:41:37 +0100
Subject: [PATCH] statfs.h: sync generic header with glibc

Fix issues with aarch64 and df with mismatching header between kernel
and libc.

Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
---
 .../linux/common-generic/bits/statfs.h        | 84 +++++++++----------
 libc/sysdeps/linux/common/fstatfs.c           |  9 --
 libc/sysdeps/linux/common/statfs.c            | 10 ---
 3 files changed, 40 insertions(+), 63 deletions(-)

diff --git a/libc/sysdeps/linux/common-generic/bits/statfs.h b/libc/sysdeps/linux/common-generic/bits/statfs.h
index a2767b49a..23519a57e 100644
--- a/libc/sysdeps/linux/common-generic/bits/statfs.h
+++ b/libc/sysdeps/linux/common-generic/bits/statfs.h
@@ -11,65 +11,61 @@
 #include <endian.h>
 #include <bits/align64bit.h>
 #include <bits/types.h>
+#include <bits/wordsize.h>
 
+/* 64-bit libc uses the kernel's 'struct statfs', accessed via the
+   statfs() syscall; 32-bit libc uses the kernel's 'struct statfs64'
+   and accesses it via the statfs64() syscall.  All the various
+   APIs offered by libc use the kernel shape for their struct statfs
+   structure; the only difference is that 32-bit programs not
+   using __USE_FILE_OFFSET64 only see the low 32 bits of some
+   of the fields (the __fsblkcnt_t and __fsfilcnt_t fields).  */
+
+#if defined __USE_FILE_OFFSET64
+# define __field64(type, type64, name) type64 name
+#elif __WORDSIZE == 64
+# define __field64(type, type64, name) type name
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+# define __field64(type, type64, name) \
+  type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
+#else
+# define __field64(type, type64, name) \
+  int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
+#endif
 
 struct statfs
   {
-    __U32_TYPE f_type;
-    __U32_TYPE f_bsize;
-#ifndef __USE_FILE_OFFSET64
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-    __U32_TYPE f_blocks;
-    __U32_TYPE __pad1;
-    __U32_TYPE f_bfree;
-    __U32_TYPE __pad2;
-    __U32_TYPE f_bavail;
-    __U32_TYPE __pad3;
-    __U32_TYPE f_files;
-    __U32_TYPE __pad4;
-    __U32_TYPE f_ffree;
-    __U32_TYPE __pad5;
-# else
-    __U32_TYPE __pad1;
-    __U32_TYPE f_blocks;
-    __U32_TYPE __pad2;
-    __U32_TYPE f_bfree;
-    __U32_TYPE __pad3;
-    __U32_TYPE f_bavail;
-    __U32_TYPE __pad4;
-    __U32_TYPE f_files;
-    __U32_TYPE __pad5;
-    __U32_TYPE f_ffree;
-# endif /* __LITTLE_ENDIAN */
-#else
-    __U64_TYPE f_blocks;
-    __U64_TYPE f_bfree;
-    __U64_TYPE f_bavail;
-    __U64_TYPE f_files;
-    __U64_TYPE f_ffree;
-#endif /* __USE_FILE_OFFSET64 */
+    __SWORD_TYPE f_type;
+    __SWORD_TYPE f_bsize;
+    __field64(__fsblkcnt_t, __fsblkcnt64_t, f_blocks);
+    __field64(__fsblkcnt_t, __fsblkcnt64_t, f_bfree);
+    __field64(__fsblkcnt_t, __fsblkcnt64_t, f_bavail);
+    __field64(__fsfilcnt_t, __fsfilcnt64_t, f_files);
+    __field64(__fsfilcnt_t, __fsfilcnt64_t, f_ffree);
     __fsid_t f_fsid;
-    __U32_TYPE f_namelen;
-    __U32_TYPE f_frsize;
-    __U32_TYPE f_flags;
-    __U32_TYPE f_spare[4];
-  } __ARCH_64BIT_ALIGNMENT__;
+    __SWORD_TYPE f_namelen;
+    __SWORD_TYPE f_frsize;
+    __SWORD_TYPE f_flags;
+    __SWORD_TYPE f_spare[4];
+  };
+
+#undef __field64
 
 #ifdef __USE_LARGEFILE64
 struct statfs64
   {
-    __U32_TYPE f_type;
-    __U32_TYPE f_bsize;
+    __SWORD_TYPE f_type;
+    __SWORD_TYPE f_bsize;
     __U64_TYPE f_blocks;
     __U64_TYPE f_bfree;
     __U64_TYPE f_bavail;
     __U64_TYPE f_files;
     __U64_TYPE f_ffree;
     __fsid_t f_fsid;
-    __U32_TYPE f_namelen;
-    __U32_TYPE f_frsize;
-    __U32_TYPE f_flags;
-    __U32_TYPE f_spare[4];
+    __SWORD_TYPE f_namelen;
+    __SWORD_TYPE f_frsize;
+    __SWORD_TYPE f_flags;
+    __SWORD_TYPE f_spare[4];
   };
 #endif
 
diff --git a/libc/sysdeps/linux/common/fstatfs.c b/libc/sysdeps/linux/common/fstatfs.c
index fcb0820eb..0b2709ce3 100644
--- a/libc/sysdeps/linux/common/fstatfs.c
+++ b/libc/sysdeps/linux/common/fstatfs.c
@@ -30,15 +30,6 @@ _syscall2(int, __libc_fstatfs, int, fd, struct statfs *, buf)
 int __libc_fstatfs (int __fildes, struct statfs *__buf)
 {
 	int err = INLINE_SYSCALL(fstatfs64, 3, __fildes, sizeof(*__buf), __buf);
-
-	if (err == 0) {
-		/* Did we overflow? */
-		if (__buf->__pad1 || __buf->__pad2 || __buf->__pad3 ||
-		    __buf->__pad4 || __buf->__pad5) {
-			__set_errno(EOVERFLOW);
-			return -1;
-		}
-	}
 	return err;
 };
 /* Redefined fstatfs because we need it for backwards compatibility */
diff --git a/libc/sysdeps/linux/common/statfs.c b/libc/sysdeps/linux/common/statfs.c
index ab9ec0e56..2990ff3e2 100644
--- a/libc/sysdeps/linux/common/statfs.c
+++ b/libc/sysdeps/linux/common/statfs.c
@@ -18,16 +18,6 @@ extern __typeof(statfs) __libc_statfs attribute_hidden;
 int __libc_statfs(const char *path, struct statfs *buf)
 {
 	int err = INLINE_SYSCALL(statfs64, 3, path, sizeof(*buf), buf);
-
-	if (err == 0) {
-		/* Did we overflow? */
-		if (buf->__pad1 || buf->__pad2 || buf->__pad3 ||
-		    buf->__pad4 || buf->__pad5) {
-			__set_errno(EOVERFLOW);
-			return -1;
-		}
-	}
-
 	return err;
 }
 # if defined __UCLIBC_LINUX_SPECIFIC__ || defined __UCLIBC_HAS_THREADS_NATIVE__
-- 
2.19.1

